﻿//using System;
//using System.Collections.Generic;
//using System.Linq;
//using System.Text;
//using Microsoft.Xna.Framework.Graphics;
//using Microsoft.Xna.Framework;

//namespace Testcraft
//{
//    class ChunkPartEx
//    {
//        private GraphicsDevice device;
//        private const int UnindexedVertex = -1;
//        private enum FaceDirection
//        {
//            PositiveX = 0,
//            NegativeX,
//            PositiveY,
//            NegativeY,
//            PositiveZ,
//            NegativeZ
//        }

//        public class BlockBuffer : IDisposable
//        {
//            public struct VertexIndex
//            {
//                public int index;
//                public int refCount;
//            }
//            public enum BufferFlags
//            {
//                None,
//                VBufferDirty = 1,
//                IBufferDirty = 2
//            }

//            public int id;
//            public GraphicsDevice device;
//            public List<VertexPositionNormalTexture> vbufferContents;
//            public DynamicVertexBuffer vbuffer;
//            public int vbufferSize;
//            public List<int> ibufferContents;
//            public DynamicIndexBuffer ibuffer;
//            public int ibufferSize;
//            public BufferFlags flags;
//            public Dictionary<int, Block> indexBufferLookup;

//            public VertexIndex[, , ,] indices;
//            //public int[, , ,] indices;

//            public BlockBuffer(int id, GraphicsDevice device, int chunkPartWidth, int chunkPartHeight)
//            {
//                this.id = id;
//                this.device = device;
//                this.vbufferContents = new List<VertexPositionNormalTexture>();
//                this.vbuffer = null;
//                this.vbufferSize = 256;
//                this.ibufferContents = new List<int>();
//                this.ibuffer = null;
//                this.ibufferSize = 256;
//                this.flags = 0;
//                this.indexBufferLookup = new Dictionary<int, Block>();

//                this.InitializeVBuffer();
//                this.InitializeIBuffer();

//                this.indices = new VertexIndex[chunkPartWidth + 1, chunkPartHeight + 1, chunkPartWidth + 1, 6];
//                //this.indices = new int[chunkPartWidth + 1, chunkPartHeight + 1, chunkPartWidth + 1, 6];

//                for (int x = 0; x < chunkPartWidth + 1; x++)
//                {
//                    for (int y = 0; y < chunkPartHeight + 1; y++)
//                    {
//                        for (int z = 0; z < chunkPartWidth + 1; z++)
//                        {
//                            for (int w = 0; w < 6; w++)
//                            {
//                                this.indices[x, y, z, w].index = -1;
//                                this.indices[x, y, z, w].refCount = 0;
//                                //this.indices[x, y, z, w] = UnindexedVertex;
//                            }
//                        }
//                    }
//                }
//            }

//            private void InitializeVBuffer()
//            {
//                if (this.vbuffer != null)
//                    this.vbuffer.Dispose();

//                this.vbuffer = new DynamicVertexBuffer(this.device, VertexPositionNormalTexture.VertexDeclaration, this.vbufferSize, BufferUsage.WriteOnly);
//            }

//            private void InitializeIBuffer()
//            {
//                if (this.ibuffer != null)
//                    this.ibuffer.Dispose();

//                this.ibuffer = new DynamicIndexBuffer(this.device, IndexElementSize.ThirtyTwoBits, this.ibufferSize, BufferUsage.WriteOnly);
//            }

//            public void RebuildVBuffer()
//            {
//                if (this.vbufferSize < this.vbufferContents.Count)
//                {
//                    while (this.vbufferSize < this.vbufferContents.Count)
//                    {
//                        this.vbufferSize *= 2;
//                    }

//                    this.InitializeVBuffer();
//                }

//                this.vbuffer.SetData<VertexPositionNormalTexture>(this.vbufferContents.ToArray());
//                this.flags &= ~BufferFlags.VBufferDirty;
//            }

//            public void RebuildIBuffer()
//            {
//                if (this.ibufferSize < this.ibufferContents.Count)
//                {
//                    while (this.ibufferSize < this.ibufferContents.Count)
//                    {
//                        this.ibufferSize *= 2;
//                    }

//                    this.InitializeIBuffer();
//                }

//                this.ibuffer.SetData<int>(this.ibufferContents.ToArray());
//                this.flags &= ~BufferFlags.IBufferDirty;
//            }

//            public void Dispose()
//            {
//                if (this.vbuffer != null)
//                    this.vbuffer.Dispose();

//                if (this.ibuffer != null)
//                    this.ibuffer.Dispose();
//            }
//        }

//        private Block[, ,] blocks;
//        public Dictionary<int, BlockBuffer> buffers;

//        public short Width { get; private set; }
//        public short Height { get; private set; }

//        public List<Block> BlocksPendingAdd { get; private set; }
//        public List<Block> BlocksPendingRemove { get; private set; }

//        public ChunkPartEx(GraphicsDevice device, short width, short height)
//        {
//            this.device = device;
//            this.Width = width;
//            this.Height = height;
//            this.blocks = new Block[width, height, width];
//            this.buffers = new Dictionary<int, BlockBuffer>();
//            this.BlocksPendingAdd = new List<Block>();
//            this.BlocksPendingRemove = new List<Block>();

//            this.InitializeMatrices();
//        }

//        private void InitializeMatrices()
//        {
//            for (int x = 0; x < this.Width; x++)
//            {
//                for (int y = 0; y < this.Height; y++)
//                {
//                    for (int z = 0; z < this.Width; z++)
//                    {
//                        this.blocks[x, y, z] = null;
//                    }
//                }
//            }
//        }

//        public void Update()
//        {
//            this.DetermineFaceVisibility();

//            for (int i = 0; i < this.BlocksPendingAdd.Count; i++)
//            {
//                Block block = this.BlocksPendingAdd[i];

//                BlockBuffer buffer;
//                if (!this.buffers.TryGetValue(block.Id, out buffer))
//                {
//                    buffer = new BlockBuffer(block.Id, this.device, this.Width, this.Height);
//                    this.buffers[block.Id] = buffer;
//                }

//                for (FaceDirection dir = FaceDirection.PositiveX; dir <= FaceDirection.NegativeZ; dir++)
//                {
//                    if (block.faceVisibility[(int)dir] && block.faceIndices[(int)dir] == -1)
//                    {
//                        this.ShowBlockFace(buffer, block, dir);
//                    }
//                    else if (!block.faceVisibility[(int)dir] && block.faceIndices[(int)dir] > -1)
//                    {
//                        this.HideBlockFace(buffer, block, dir);
//                    }
//                }
//            }

//            for (int i = 0; i < this.BlocksPendingRemove.Count; i++)
//            {
//                int blockX = this.BlocksPendingRemove[i].X % this.Width;
//                int blockY = this.BlocksPendingRemove[i].Y % this.Height;
//                int blockZ = this.BlocksPendingRemove[i].Z % this.Width;

//                Block block = this.blocks[blockX, blockY, blockZ];

//                if (block == null || block.faceVisibility.All(x => !x))
//                    continue;


//                //if ()
//                //{
//                //    // Block is already completely invisible. Just set it to null in the block matrix and continue.
//                //    this.blocks[blockX, blockY, blockZ] = null;
//                //    continue;
//                //}

//                BlockBuffer buffer;
//                if (!this.buffers.TryGetValue(block.Id, out buffer))
//                {
//                    buffer = new BlockBuffer(block.Id, this.device, this.Width, this.Height);
//                    this.buffers[block.Id] = buffer;
//                }

//                Block neighbor;
//                BlockBuffer neighborBuffer;
//                for (FaceDirection dir = FaceDirection.PositiveX; dir <= FaceDirection.NegativeZ; dir++)
//                {
//                    this.HideBlockFace(buffer, block, dir);
//                    block.faceVisibility[(int)dir] = false;

//                    if (this.TryGetBlockFromDirection(block.X, block.Y, block.Z, dir, out neighbor))
//                    {
//                        if (neighbor == null)
//                        {
//                            short airX, airY, airZ;
//                            this.GetLocationByDirection(block.X, block.Y, block.Z, dir, out airX, out airY, out airZ);
//                            this.SetVisibilityOfAdjacentFaces(airX, airY, airZ, true, true);
//                        }
//                        else
//                        {
//                            neighborBuffer = this.buffers[neighbor.Id];

//                            this.ShowBlockFace(neighborBuffer, neighbor, this.GetOppositeDirection(dir));
//                            neighbor.faceVisibility[(int)this.GetOppositeDirection(dir)] = true;
//                        }
//                    }
//                }

                

//                this.blocks[blockX, blockY, blockZ] = null;

//            }

//            this.BlocksPendingAdd.Clear();
//            this.BlocksPendingRemove.Clear();

//            List<BlockBuffer> buffersToRemove = null;
//            foreach (BlockBuffer buffer in this.buffers.Values)
//            {
//                if ((buffer.flags & BlockBuffer.BufferFlags.VBufferDirty) > 0)
//                {
//                    buffer.RebuildVBuffer();
//                }

//                if ((buffer.flags & BlockBuffer.BufferFlags.IBufferDirty) > 0)
//                {
//                    if (buffer.ibufferContents.Count == 0)
//                    {
//                        if (buffersToRemove == null)
//                            buffersToRemove = new List<BlockBuffer>();

//                        buffersToRemove.Add(buffer);
//                    }
//                    else
//                    {
//                        buffer.RebuildIBuffer();
//                    }
//                }
//            }

//            if (buffersToRemove != null)
//            {
//                for (int i = 0; i < buffersToRemove.Count; i++)
//                {
//                    this.buffers.Remove(buffersToRemove[i].id);
//                    buffersToRemove[i].Dispose();
//                }
//            }
//        }

//        private bool IsAirBlockClosedBySolidBlocks(short x, short y, short z)
//        {
//            bool closed = true;
//            Block neighbor = null;
//            for (FaceDirection dir = FaceDirection.PositiveX; dir <= FaceDirection.NegativeZ; dir++)
//            {
//                if ((!TryGetBlockFromDirection(x, y, z, dir, out neighbor) || neighbor == null || neighbor.Transparent))
//                {
//                    closed = false;
//                    break;
//                }
//            }

//            return closed;
//        }

//        private bool WillAirBlockBeClosedByNewBlock(short x, short y, short z, FaceDirection directionToNewBlock)
//        {
//            bool closed = true;
//            Block neighbor = null;
//            for (FaceDirection dir = FaceDirection.PositiveX; dir <= FaceDirection.NegativeZ; dir++)
//            {
//                if (dir != directionToNewBlock && (!TryGetBlockFromDirection(x,y ,z, dir, out neighbor) || neighbor == null || neighbor.Transparent))
//                {
//                    closed = false;
//                    break;
//                }
//            }

//            return closed;
//        }

//        private void SetVisibilityOfAdjacentFaces(short x, short y, short z, bool visibility, bool updateFaces)
//        {
//            Block neighbor = null;
//            BlockBuffer neighborBuffer;
//            for (FaceDirection dir = FaceDirection.PositiveX; dir <= FaceDirection.NegativeZ; dir++)
//            {
//                if (TryGetBlockFromDirection(x, y, z, dir, out neighbor) && neighbor != null)
//                {
//                    FaceDirection oppositeDirection = this.GetOppositeDirection(dir);
//                    neighbor.faceVisibility[(int)oppositeDirection] = visibility;

//                    if (updateFaces)
//                    {
//                        if (visibility && neighbor.faceIndices[(int)oppositeDirection] == -1)
//                        {
//                            neighborBuffer = this.buffers[neighbor.Id];
//                            this.ShowBlockFace(neighborBuffer, neighbor, oppositeDirection);
//                        }
//                        else if (!visibility && neighbor.faceIndices[(int)oppositeDirection] > -1)
//                        {
//                            neighborBuffer = this.buffers[neighbor.Id];
//                            this.HideBlockFace(neighborBuffer, neighbor, oppositeDirection);
//                        }
//                    }
//                }
//            }
//        }

//        private void DetermineFaceVisibility()
//        {
//            for (int i = 0; i < this.BlocksPendingAdd.Count; i++)
//            {
//                Block block = this.BlocksPendingAdd[i];

//                short blockX = (short)(block.X % this.Width);
//                short blockY = (short)(block.Y % this.Height);
//                short blockZ = (short)(block.Z % this.Width);

//                if (this.blocks[blockX, blockY, blockZ] != null)
//                    continue;

//                /* Positive X */
//                if (blockX == this.Width - 1 ||
//                    this.blocks[blockX + 1, blockY, blockZ] == null ||
//                    this.blocks[blockX + 1, blockY, blockZ].Transparent)
//                {
//                    if (this.WillAirBlockBeClosedByNewBlock((short)(blockX + 1), blockY, blockZ, FaceDirection.NegativeX))
//                    {
//                        //this.SetVisibilityOfAdjacentFaces((short)(blockX + 1), blockY, blockZ, false, false);
//                    }
//                    //else
//                    {
//                        block.faceVisibility[(int)FaceDirection.PositiveX] = true;
//                    }
//                }
//                else if (this.blocks[blockX + 1, blockY, blockZ] != null && !block.Transparent)
//                {
//                    this.blocks[blockX + 1, blockY, blockZ].faceVisibility[(int)FaceDirection.NegativeX] = false;
//                }

//                /* Negative X */
//                if (blockX == 0 ||
//                    this.blocks[blockX - 1, blockY, blockZ] == null ||
//                    this.blocks[blockX - 1, blockY, blockZ].Transparent)
//                {
//                    if (this.WillAirBlockBeClosedByNewBlock((short)(blockX - 1), blockY, blockZ, FaceDirection.PositiveX))
//                    {
//                        this.SetVisibilityOfAdjacentFaces((short)(blockX - 1), blockY, blockZ, false, false);
//                    }
//                    else
//                    {
//                        block.faceVisibility[(int)FaceDirection.NegativeX] = true;
//                    }
//                }
//                else if(this.blocks[blockX - 1, blockY, blockZ] != null && !block.Transparent)
//                {
//                    this.blocks[blockX - 1, blockY, blockZ].faceVisibility[(int)FaceDirection.PositiveX] = false;
//                }

//                /* Positive Y */
//                if (blockY == this.Height - 1 ||
//                    this.blocks[blockX, blockY + 1, blockZ] == null ||
//                    this.blocks[blockX, blockY + 1, blockZ].Transparent)
//                {
//                    block.faceVisibility[(int)FaceDirection.PositiveY] = true;
//                }
//                else if (this.blocks[blockX, blockY + 1, blockZ] != null && !block.Transparent)
//                {
//                    this.blocks[blockX, blockY + 1, blockZ].faceVisibility[(int)FaceDirection.NegativeY] = false;
//                }

//                /* Negative Y */
//                if (blockY == 0 ||
//                    this.blocks[blockX, blockY - 1, blockZ] == null ||
//                    this.blocks[blockX, blockY - 1, blockZ].Transparent)
//                {
//                    block.faceVisibility[(int)FaceDirection.NegativeY] = true;
//                }
//                else if (!block.Transparent)
//                {
//                    this.blocks[blockX, blockY - 1, blockZ].faceVisibility[(int)FaceDirection.PositiveY] = false;
//                }

//                /* Positive Z */
//                if (blockZ == this.Width - 1 ||
//                    this.blocks[blockX, blockY, blockZ + 1] == null ||
//                    this.blocks[blockX, blockY, blockZ + 1].Transparent)
//                {
//                    block.faceVisibility[(int)FaceDirection.PositiveZ] = true;
//                }
//                else if(!block.Transparent)
//                {
//                    this.blocks[blockX, blockY, blockZ + 1].faceVisibility[(int)FaceDirection.NegativeZ] = false;
//                }

//                /* Negative Z */
//                if (blockZ == 0 ||
//                    this.blocks[blockX, blockY, blockZ - 1] == null ||
//                    this.blocks[blockX, blockY, blockZ - 1].Transparent)
//                {
//                    block.faceVisibility[(int)FaceDirection.NegativeZ] = true;
//                }
//                else if (!block.Transparent)
//                {
//                    this.blocks[blockX, blockY, blockZ - 1].faceVisibility[(int)FaceDirection.PositiveZ] = false;
//                }

//                this.blocks[blockX, blockY, blockZ] = block;
//            }
//        }

//        private FaceDirection GetOppositeDirection(FaceDirection direction)
//        {
//            switch (direction)
//            {
//                case FaceDirection.PositiveX:
//                    return FaceDirection.NegativeX;
//                case FaceDirection.NegativeX:
//                    return FaceDirection.PositiveX;
//                case FaceDirection.PositiveY:
//                    return FaceDirection.NegativeY;
//                case FaceDirection.NegativeY:
//                    return FaceDirection.PositiveY;
//                case FaceDirection.PositiveZ:
//                    return FaceDirection.NegativeZ;
//                case FaceDirection.NegativeZ:
//                    return FaceDirection.PositiveZ;
//                default:
//                    throw new Exception("Detta ska inte kunna hända!!");
//            }
//        }

//        private void HideBlockFace(BlockBuffer buffer, Block block, FaceDirection face)
//        {

//            int faceIndex = block.faceIndices[(int)face];
//            if (faceIndex == -1)
//                return;



//            //if (buffer.indexBufferLookup[faceIndex] != block)
//            //    throw new EncoderFallbackException();

//            buffer.ibufferContents.RemoveRange(faceIndex, 6);
//            block.faceIndices[(int)face] = -1;

//            for (int i = faceIndex + 6; i < buffer.ibufferContents.Count + 6; i += 6)
//            {
                
//                Block blockToUpdate;
//                blockToUpdate = buffer.indexBufferLookup[i];
//                //if (buffer.indexBufferLookup.TryGetValue(i, out blockToUpdate))
//                //{
//                    buffer.indexBufferLookup[i - 6] = blockToUpdate;


//                    for (int j = 0; j < 6; j++)
//                    {
//                        if (blockToUpdate.faceIndices[j] == i)
//                        {
//                            blockToUpdate.faceIndices[j] -= 6;
//                            break;
//                        }
//                    }

//                //}
//                //else
//                //{
//                //    throw new FieldAccessException();
//                //}
//                //buffer.indexBufferLookup.Remove(i);
//                //buffer.indexBufferLookup.Add(i - 6, blockToUpdate);
//            }


//            //for (int x = 0; x < this.Width; x++)
//            //{
//            //    for (int y = 0; y < this.Height; y++)
//            //    {
//            //        for (int z = 0; z < this.Width; z++)
//            //        {
//            //            if (this.blocks[x, y, z] != null)
//            //            {
//            //                for (int i = 0; i < 6; i++)
//            //                {
//            //                    if (this.blocks[x, y, z].faceIndices[i] > faceIndex)
//            //                    {
//            //                        buffer.indexBufferLookup.Remove(this.blocks[x, y, z].faceIndices[i]);
//            //                        buffer.indexBufferLookup[this.blocks[x, y, z].faceIndices[i] - 6] = this.blocks[x, y, z];
//            //                        this.blocks[x, y, z].faceIndices[i] -= 6;
//            //                    }
//            //                }
//            //            }
//            //        }
//            //    }
//            //}

//            buffer.flags |= BlockBuffer.BufferFlags.IBufferDirty;
//        }

//        private void ShowBlockFace(BlockBuffer buffer, Block block, FaceDirection face)
//        {
//            int chunkPartX = block.X % this.Width;
//            int chunkPartY = block.Y % this.Height;
//            int chunkPartZ = block.Z % this.Width;

//            if (block.faceIndices[(int)face] > -1)
//                return;

//            Testcraft.ChunkPartEx.BlockBuffer.VertexIndex topLeftIndex, topRightIndex, lowerLeftIndex, lowerRightIndex;
//            //int topLeftIndex.index, topRightIndex, lowerLeftIndex, lowerRightIndex;
//            switch (face)
//            {
//                case FaceDirection.PositiveX:

//                    // Block to the right does not exist or is transparent, so our blocks rightmost face is visible.

//                    topLeftIndex = buffer.indices[chunkPartX + 1, chunkPartY + 1, chunkPartZ + 1, (int)FaceDirection.PositiveX];
//                    topRightIndex = buffer.indices[chunkPartX + 1, chunkPartY + 1, chunkPartZ, (int)FaceDirection.PositiveX];
//                    lowerLeftIndex = buffer.indices[chunkPartX + 1, chunkPartY, chunkPartZ + 1, (int)FaceDirection.PositiveX];
//                    lowerRightIndex = buffer.indices[chunkPartX + 1, chunkPartY, chunkPartZ, (int)FaceDirection.PositiveX];

//                    if (topLeftIndex.index == UnindexedVertex)
//                    {
//                        topLeftIndex.index = buffer.vbufferContents.Count;
//                        buffer.indices[chunkPartX + 1, chunkPartY + 1, chunkPartZ + 1, (int)FaceDirection.PositiveX] = topLeftIndex;

//                        buffer.vbufferContents.Add(new VertexPositionNormalTexture(
//                            new Vector3(chunkPartX + 0.5f, chunkPartY + 0.5f, chunkPartZ + 0.5f), Vector3.Right, new Vector2(-chunkPartZ, -chunkPartY)));

//                        buffer.flags |= BlockBuffer.BufferFlags.VBufferDirty;
//                    }

//                    if (topRightIndex.index == UnindexedVertex)
//                    {
//                        topRightIndex.index = buffer.vbufferContents.Count;
//                        buffer.indices[chunkPartX + 1, chunkPartY + 1, chunkPartZ, (int)FaceDirection.PositiveX] = topRightIndex;

//                        buffer.vbufferContents.Add(new VertexPositionNormalTexture(
//                            new Vector3(chunkPartX + 0.5f, chunkPartY + 0.5f, chunkPartZ - 0.5f), Vector3.Right, new Vector2(-chunkPartZ + 1, -chunkPartY)));

//                        buffer.flags |= BlockBuffer.BufferFlags.VBufferDirty;
//                    }

//                    if (lowerLeftIndex.index == UnindexedVertex)
//                    {
//                        lowerLeftIndex.index = buffer.vbufferContents.Count;
//                        buffer.indices[chunkPartX + 1, chunkPartY, chunkPartZ + 1, (int)FaceDirection.PositiveX] = lowerLeftIndex;

//                        buffer.vbufferContents.Add(new VertexPositionNormalTexture(
//                            new Vector3(chunkPartX + 0.5f, chunkPartY - 0.5f, chunkPartZ + 0.5f), Vector3.Right, new Vector2(-chunkPartZ, -chunkPartY + 1)));

//                        buffer.flags |= BlockBuffer.BufferFlags.VBufferDirty;
//                    }

//                    if (lowerRightIndex.index == UnindexedVertex)
//                    {
//                        lowerRightIndex.index = buffer.vbufferContents.Count;
//                        buffer.indices[chunkPartX + 1, chunkPartY, chunkPartZ, (int)FaceDirection.PositiveX] = lowerRightIndex;

//                        buffer.vbufferContents.Add(new VertexPositionNormalTexture(
//                            new Vector3(chunkPartX + 0.5f, chunkPartY - 0.5f, chunkPartZ - 0.5f), Vector3.Right, new Vector2(-chunkPartZ + 1, -chunkPartY + 1)));

//                        buffer.flags |= BlockBuffer.BufferFlags.VBufferDirty;
//                    }

//                    block.faceIndices[(int)FaceDirection.PositiveX] = buffer.ibufferContents.Count;

//                    // TVIVELAKTIGT
//                    buffer.indexBufferLookup[buffer.ibufferContents.Count] = block;

//                    buffer.ibufferContents.AddRange(new int[] { topLeftIndex.index, topRightIndex.index, lowerLeftIndex.index, topRightIndex.index, lowerRightIndex.index, lowerLeftIndex.index });

//                    buffer.flags |= BlockBuffer.BufferFlags.IBufferDirty;

//                    break;
//                case FaceDirection.NegativeX:
//                    // Block to the left does not exist or is transparent, so our blocks leftmost face is visible.

//                    topLeftIndex = buffer.indices[chunkPartX, chunkPartY + 1, chunkPartZ, (int)FaceDirection.NegativeX];
//                    topRightIndex = buffer.indices[chunkPartX, chunkPartY + 1, chunkPartZ + 1, (int)FaceDirection.NegativeX];
//                    lowerLeftIndex = buffer.indices[chunkPartX, chunkPartY, chunkPartZ, (int)FaceDirection.NegativeX];
//                    lowerRightIndex = buffer.indices[chunkPartX, chunkPartY, chunkPartZ + 1, (int)FaceDirection.NegativeX];

//                    if (topLeftIndex.index == UnindexedVertex)
//                    {
//                        topLeftIndex.index = buffer.vbufferContents.Count;
//                        buffer.indices[chunkPartX, chunkPartY + 1, chunkPartZ, (int)FaceDirection.NegativeX] = topLeftIndex;

//                        buffer.vbufferContents.Add(new VertexPositionNormalTexture(
//                            new Vector3(chunkPartX - 0.5f, chunkPartY + 0.5f, chunkPartZ - 0.5f), Vector3.Left, new Vector2(chunkPartZ, -chunkPartY)));

//                        buffer.flags |= BlockBuffer.BufferFlags.VBufferDirty;
//                    }

//                    if (topRightIndex.index == UnindexedVertex)
//                    {
//                        topRightIndex.index = buffer.vbufferContents.Count;
//                        buffer.indices[chunkPartX, chunkPartY + 1, chunkPartZ + 1, (int)FaceDirection.NegativeX] = topRightIndex;

//                        buffer.vbufferContents.Add(new VertexPositionNormalTexture(
//                            new Vector3(chunkPartX - 0.5f, chunkPartY + 0.5f, chunkPartZ + 0.5f), Vector3.Left, new Vector2(chunkPartZ + 1, -chunkPartY)));

//                        buffer.flags |= BlockBuffer.BufferFlags.VBufferDirty;
//                    }

//                    if (lowerLeftIndex.index == UnindexedVertex)
//                    {
//                        lowerLeftIndex.index = buffer.vbufferContents.Count;
//                        buffer.indices[chunkPartX, chunkPartY, chunkPartZ, (int)FaceDirection.NegativeX] = lowerLeftIndex;

//                        buffer.vbufferContents.Add(new VertexPositionNormalTexture(
//                            new Vector3(chunkPartX - 0.5f, chunkPartY - 0.5f, chunkPartZ - 0.5f), Vector3.Left, new Vector2(chunkPartZ, -chunkPartY + 1)));

//                        buffer.flags |= BlockBuffer.BufferFlags.VBufferDirty;
//                    }

//                    if (lowerRightIndex.index == UnindexedVertex)
//                    {
//                        lowerRightIndex.index = buffer.vbufferContents.Count;
//                        buffer.indices[chunkPartX, chunkPartY, chunkPartZ + 1, (int)FaceDirection.NegativeX] = lowerRightIndex;

//                        buffer.vbufferContents.Add(new VertexPositionNormalTexture(
//                            new Vector3(chunkPartX - 0.5f, chunkPartY - 0.5f, chunkPartZ + 0.5f), Vector3.Left, new Vector2(chunkPartZ + 1, -chunkPartY + 1)));

//                        buffer.flags |= BlockBuffer.BufferFlags.VBufferDirty;
//                    }

//                    block.faceIndices[(int)FaceDirection.NegativeX] = buffer.ibufferContents.Count;

//                    buffer.indexBufferLookup[buffer.ibufferContents.Count] = block;

//                    buffer.ibufferContents.AddRange(new int[] { topLeftIndex.index, topRightIndex.index, lowerLeftIndex.index, topRightIndex.index, lowerRightIndex.index, lowerLeftIndex.index });

//                    buffer.flags |= BlockBuffer.BufferFlags.IBufferDirty;


//                    break;
//                case FaceDirection.PositiveY:
//                    // Block above does not exist or is transparent, so our blocks topmost face is visible.

//                    topLeftIndex = buffer.indices[chunkPartX, chunkPartY + 1, chunkPartZ, (int)FaceDirection.PositiveY];
//                    topRightIndex = buffer.indices[chunkPartX + 1, chunkPartY + 1, chunkPartZ, (int)FaceDirection.PositiveY];
//                    lowerLeftIndex = buffer.indices[chunkPartX, chunkPartY + 1, chunkPartZ + 1, (int)FaceDirection.PositiveY];
//                    lowerRightIndex = buffer.indices[chunkPartX + 1, chunkPartY + 1, chunkPartZ + 1, (int)FaceDirection.PositiveY];

//                    if (topLeftIndex.index == UnindexedVertex)
//                    {
//                        topLeftIndex.index = buffer.vbufferContents.Count;
                        
//                        buffer.vbufferContents.Add(new VertexPositionNormalTexture(
//                            new Vector3(chunkPartX - 0.5f, chunkPartY + 0.5f, chunkPartZ - 0.5f), Vector3.Up, new Vector2(chunkPartX, chunkPartZ)));

//                        buffer.flags |= BlockBuffer.BufferFlags.VBufferDirty;
//                    }

//                    buffer.indices[chunkPartX, chunkPartY + 1, chunkPartZ, (int)FaceDirection.PositiveY] = topLeftIndex;

//                    if (topRightIndex.index == UnindexedVertex)
//                    {
//                        topRightIndex.index = buffer.vbufferContents.Count;
                        

//                        buffer.vbufferContents.Add(new VertexPositionNormalTexture(
//                            new Vector3(chunkPartX + 0.5f, chunkPartY + 0.5f, chunkPartZ - 0.5f), Vector3.Up, new Vector2(chunkPartX + 1, chunkPartZ)));

//                        buffer.flags |= BlockBuffer.BufferFlags.VBufferDirty;
//                    }

//                    buffer.indices[chunkPartX + 1, chunkPartY + 1, chunkPartZ, (int)FaceDirection.PositiveY] = topRightIndex;

//                    if (lowerLeftIndex.index == UnindexedVertex)
//                    {
//                        lowerLeftIndex.index = buffer.vbufferContents.Count;
                        

//                        buffer.vbufferContents.Add(new VertexPositionNormalTexture(
//                            new Vector3(chunkPartX - 0.5f, chunkPartY + 0.5f, chunkPartZ + 0.5f), Vector3.Up, new Vector2(chunkPartX, chunkPartZ + 1)));

//                        buffer.flags |= BlockBuffer.BufferFlags.VBufferDirty;
//                    }

//                    buffer.indices[chunkPartX, chunkPartY + 1, chunkPartZ + 1, (int)FaceDirection.PositiveY] = lowerLeftIndex;

//                    if (lowerRightIndex.index == UnindexedVertex)
//                    {
//                        lowerRightIndex.index = buffer.vbufferContents.Count;
                        

//                        buffer.vbufferContents.Add(new VertexPositionNormalTexture(
//                            new Vector3(chunkPartX + 0.5f, chunkPartY + 0.5f, chunkPartZ + 0.5f), Vector3.Up, new Vector2(chunkPartX + 1, chunkPartZ + 1)));

//                        buffer.flags |= BlockBuffer.BufferFlags.VBufferDirty;
//                    }

//                    buffer.indices[chunkPartX + 1, chunkPartY + 1, chunkPartZ + 1, (int)FaceDirection.PositiveY] = lowerRightIndex;

//                    block.faceIndices[(int)FaceDirection.PositiveY] = buffer.ibufferContents.Count;

//                    buffer.indexBufferLookup[buffer.ibufferContents.Count] = block;

//                    buffer.ibufferContents.AddRange(new int[] { topLeftIndex.index, topRightIndex.index, lowerLeftIndex.index, topRightIndex.index, lowerRightIndex.index, lowerLeftIndex.index });

//                    buffer.flags |= BlockBuffer.BufferFlags.IBufferDirty;


//                    break;
//                case FaceDirection.NegativeY:
//                    // Block below does not exist or is transparent, so our blocks bottommost face is visible.

//                    topLeftIndex = buffer.indices[chunkPartX, chunkPartY, chunkPartZ + 1, (int)FaceDirection.NegativeY];
//                    topRightIndex = buffer.indices[chunkPartX + 1, chunkPartY, chunkPartZ + 1, (int)FaceDirection.NegativeY];
//                    lowerLeftIndex = buffer.indices[chunkPartX, chunkPartY, chunkPartZ, (int)FaceDirection.NegativeY];
//                    lowerRightIndex = buffer.indices[chunkPartX + 1, chunkPartY, chunkPartZ, (int)FaceDirection.NegativeY];

//                    if (topLeftIndex.index == UnindexedVertex)
//                    {
//                        topLeftIndex.index = buffer.vbufferContents.Count;
                        

//                        buffer.vbufferContents.Add(new VertexPositionNormalTexture(
//                            new Vector3(chunkPartX - 0.5f, chunkPartY - 0.5f, chunkPartZ + 0.5f), Vector3.Down, new Vector2(chunkPartX, -chunkPartZ)));

//                        buffer.flags |= BlockBuffer.BufferFlags.VBufferDirty;
//                    }

//                    buffer.indices[chunkPartX, chunkPartY, chunkPartZ + 1, (int)FaceDirection.NegativeY] = topLeftIndex;

//                    if (topRightIndex.index == UnindexedVertex)
//                    {
//                        topRightIndex.index = buffer.vbufferContents.Count;
                        

//                        buffer.vbufferContents.Add(new VertexPositionNormalTexture(
//                            new Vector3(chunkPartX + 0.5f, chunkPartY - 0.5f, chunkPartZ + 0.5f), Vector3.Down, new Vector2(chunkPartX + 1, -chunkPartZ)));

//                        buffer.flags |= BlockBuffer.BufferFlags.VBufferDirty;
//                    }

//                    buffer.indices[chunkPartX + 1, chunkPartY, chunkPartZ + 1, (int)FaceDirection.NegativeY] = topRightIndex;

//                    if (lowerLeftIndex.index == UnindexedVertex)
//                    {
//                        lowerLeftIndex.index = buffer.vbufferContents.Count;
                        

//                        buffer.vbufferContents.Add(new VertexPositionNormalTexture(
//                            new Vector3(chunkPartX - 0.5f, chunkPartY - 0.5f, chunkPartZ - 0.5f), Vector3.Down, new Vector2(chunkPartX, -chunkPartZ + 1)));

//                        buffer.flags |= BlockBuffer.BufferFlags.VBufferDirty;
//                    }

//                    buffer.indices[chunkPartX, chunkPartY, chunkPartZ, (int)FaceDirection.NegativeY] = lowerLeftIndex;

//                    if (lowerRightIndex.index == UnindexedVertex)
//                    {
//                        lowerRightIndex.index = buffer.vbufferContents.Count;
                        

//                        buffer.vbufferContents.Add(new VertexPositionNormalTexture(
//                            new Vector3(chunkPartX + 0.5f, chunkPartY - 0.5f, chunkPartZ - 0.5f), Vector3.Down, new Vector2(chunkPartX + 1, -chunkPartZ + 1)));

//                        buffer.flags |= BlockBuffer.BufferFlags.VBufferDirty;
//                    }

//                    buffer.indices[chunkPartX + 1, chunkPartY, chunkPartZ, (int)FaceDirection.NegativeY] = lowerRightIndex;

//                    block.faceIndices[(int)FaceDirection.NegativeY] = buffer.ibufferContents.Count;

//                    buffer.indexBufferLookup[buffer.ibufferContents.Count] = block;

//                    buffer.ibufferContents.AddRange(new int[] { topLeftIndex.index, topRightIndex.index, lowerLeftIndex.index, topRightIndex.index, lowerRightIndex.index, lowerLeftIndex.index });

//                    buffer.flags |= BlockBuffer.BufferFlags.IBufferDirty;

//                    break;
//                case FaceDirection.PositiveZ:
//                    // Block in front does not exist or is transparent, so our blocks front face is visible.

//                    topLeftIndex = buffer.indices[chunkPartX, chunkPartY + 1, chunkPartZ + 1, (int)FaceDirection.PositiveZ];
//                    topRightIndex = buffer.indices[chunkPartX + 1, chunkPartY + 1, chunkPartZ + 1, (int)FaceDirection.PositiveZ];
//                    lowerLeftIndex = buffer.indices[chunkPartX, chunkPartY, chunkPartZ + 1, (int)FaceDirection.PositiveZ];
//                    lowerRightIndex = buffer.indices[chunkPartX + 1, chunkPartY, chunkPartZ + 1, (int)FaceDirection.PositiveZ];

//                    topLeftIndex.refCount++;
//                    topRightIndex.refCount++;
//                    lowerLeftIndex.refCount++;
//                    lowerRightIndex.refCount++;

//                    if (topLeftIndex.index == UnindexedVertex)
//                    {
//                        topLeftIndex.index = buffer.vbufferContents.Count;
                        

//                        buffer.vbufferContents.Add(new VertexPositionNormalTexture(
//                            new Vector3(chunkPartX - 0.5f, chunkPartY + 0.5f, chunkPartZ + 0.5f), Vector3.Backward, new Vector2(chunkPartX, -chunkPartY)));

//                        buffer.flags |= BlockBuffer.BufferFlags.VBufferDirty;
//                    }

//                    buffer.indices[chunkPartX, chunkPartY + 1, chunkPartZ + 1, (int)FaceDirection.PositiveZ] = topLeftIndex;

//                    if (topRightIndex.index == UnindexedVertex)
//                    {
//                        topRightIndex.index = buffer.vbufferContents.Count;
                        

//                        buffer.vbufferContents.Add(new VertexPositionNormalTexture(
//                            new Vector3(chunkPartX + 0.5f, chunkPartY + 0.5f, chunkPartZ + 0.5f), Vector3.Backward, new Vector2(chunkPartX + 1, -chunkPartY)));

//                        buffer.flags |= BlockBuffer.BufferFlags.VBufferDirty;
//                    }

//                    buffer.indices[chunkPartX + 1, chunkPartY + 1, chunkPartZ + 1, (int)FaceDirection.PositiveZ] = topRightIndex;

//                    if (lowerLeftIndex.index == UnindexedVertex)
//                    {
//                        lowerLeftIndex.index = buffer.vbufferContents.Count;
                        

//                        buffer.vbufferContents.Add(new VertexPositionNormalTexture(
//                            new Vector3(chunkPartX - 0.5f, chunkPartY - 0.5f, chunkPartZ + 0.5f), Vector3.Backward, new Vector2(chunkPartX, -chunkPartY + 1)));

//                        buffer.flags |= BlockBuffer.BufferFlags.VBufferDirty;
//                    }

//                    buffer.indices[chunkPartX, chunkPartY, chunkPartZ + 1, (int)FaceDirection.PositiveZ] = lowerLeftIndex;

//                    if (lowerRightIndex.index == UnindexedVertex)
//                    {
//                        lowerRightIndex.index = buffer.vbufferContents.Count;
                        

//                        buffer.vbufferContents.Add(new VertexPositionNormalTexture(
//                            new Vector3(chunkPartX + 0.5f, chunkPartY - 0.5f, chunkPartZ + 0.5f), Vector3.Backward, new Vector2(chunkPartX + 1, -chunkPartY + 1)));

//                        buffer.flags |= BlockBuffer.BufferFlags.VBufferDirty;
//                    }

//                    buffer.indices[chunkPartX + 1, chunkPartY, chunkPartZ + 1, (int)FaceDirection.PositiveZ] = lowerRightIndex;

//                    block.faceIndices[(int)FaceDirection.PositiveZ] = buffer.ibufferContents.Count;

//                    buffer.indexBufferLookup[buffer.ibufferContents.Count] = block;

//                    buffer.ibufferContents.AddRange(new int[] { topLeftIndex.index, topRightIndex.index, lowerLeftIndex.index, topRightIndex.index, lowerRightIndex.index, lowerLeftIndex.index });

//                    buffer.flags |= BlockBuffer.BufferFlags.IBufferDirty;


//                    break;
//                case FaceDirection.NegativeZ:
//                    // Block in back does not exist or is transparent, so our blocks back face is visible.

//                    topLeftIndex = buffer.indices[chunkPartX + 1, chunkPartY + 1, chunkPartZ, (int)FaceDirection.NegativeZ];
//                    topRightIndex = buffer.indices[chunkPartX, chunkPartY + 1, chunkPartZ, (int)FaceDirection.NegativeZ];
//                    lowerLeftIndex = buffer.indices[chunkPartX + 1, chunkPartY, chunkPartZ, (int)FaceDirection.NegativeZ];
//                    lowerRightIndex = buffer.indices[chunkPartX, chunkPartY, chunkPartZ, (int)FaceDirection.NegativeZ];

//                    if (topLeftIndex.index == UnindexedVertex)
//                    {
//                        topLeftIndex.index = buffer.vbufferContents.Count;
                        

//                        buffer.vbufferContents.Add(new VertexPositionNormalTexture(
//                            new Vector3(chunkPartX + 0.5f, chunkPartY + 0.5f, chunkPartZ - 0.5f), Vector3.Forward, new Vector2(-chunkPartX, -chunkPartY)));

//                        buffer.flags |= BlockBuffer.BufferFlags.VBufferDirty;
//                    }

//                    buffer.indices[chunkPartX + 1, chunkPartY + 1, chunkPartZ, (int)FaceDirection.NegativeZ] = topLeftIndex;

//                    if (topRightIndex.index == UnindexedVertex)
//                    {
//                        topRightIndex.index = buffer.vbufferContents.Count;
                        

//                        buffer.vbufferContents.Add(new VertexPositionNormalTexture(
//                            new Vector3(chunkPartX - 0.5f, chunkPartY + 0.5f, chunkPartZ - 0.5f), Vector3.Forward, new Vector2(-chunkPartX + 1, -chunkPartY)));

//                        buffer.flags |= BlockBuffer.BufferFlags.VBufferDirty;
//                    }

//                    buffer.indices[chunkPartX, chunkPartY + 1, chunkPartZ, (int)FaceDirection.NegativeZ] = topRightIndex;

//                    if (lowerLeftIndex.index == UnindexedVertex)
//                    {
//                        lowerLeftIndex.index = buffer.vbufferContents.Count;
                        

//                        buffer.vbufferContents.Add(new VertexPositionNormalTexture(
//                            new Vector3(chunkPartX + 0.5f, chunkPartY - 0.5f, chunkPartZ - 0.5f), Vector3.Forward, new Vector2(-chunkPartX, -chunkPartY + 1)));

//                        buffer.flags |= BlockBuffer.BufferFlags.VBufferDirty;
//                    }

//                    buffer.indices[chunkPartX + 1, chunkPartY, chunkPartZ, (int)FaceDirection.NegativeZ] = lowerLeftIndex;

//                    if (lowerRightIndex.index == UnindexedVertex)
//                    {
//                        lowerRightIndex.index = buffer.vbufferContents.Count;
                        

//                        buffer.vbufferContents.Add(new VertexPositionNormalTexture(
//                            new Vector3(chunkPartX - 0.5f, chunkPartY - 0.5f, chunkPartZ - 0.5f), Vector3.Forward, new Vector2(-chunkPartX + 1, -chunkPartY + 1)));

//                        buffer.flags |= BlockBuffer.BufferFlags.VBufferDirty;
//                    }

//                    buffer.indices[chunkPartX, chunkPartY, chunkPartZ, (int)FaceDirection.NegativeZ] = lowerRightIndex;

//                    block.faceIndices[(int)FaceDirection.NegativeZ] = buffer.ibufferContents.Count;

//                    buffer.indexBufferLookup[buffer.ibufferContents.Count] = block;

//                    buffer.ibufferContents.AddRange(new int[] { topLeftIndex.index, topRightIndex.index, lowerLeftIndex.index, topRightIndex.index, lowerRightIndex.index, lowerLeftIndex.index });

//                    buffer.flags |= BlockBuffer.BufferFlags.IBufferDirty;


//                    break;
//            }


//        }

//        private void GetLocationByDirection(short x, short y, short z, FaceDirection dir, out short resultX, out short resultY, out short resultZ)
//        {
//            switch (dir)
//            {
//                case FaceDirection.PositiveX:
//                    x += 1;
//                    break;
//                case FaceDirection.NegativeX:
//                    x -= 1;
//                    break;
//                case FaceDirection.PositiveY:
//                    y += 1;
//                    break;
//                case FaceDirection.NegativeY:
//                    y -= 1;
//                    break;
//                case FaceDirection.PositiveZ:
//                    z += 1;
//                    break;
//                case FaceDirection.NegativeZ:
//                    z -= 1;
//                    break;

//            }

//            resultX = x;
//            resultY = y;
//            resultZ = z;
//        }

//        private bool TryGetBlockFromDirection(short x, short y, short z, FaceDirection dir, out Block result)
//        {
//            bool success;
//            this.GetLocationByDirection(x, y, z, dir, out x, out y, out z);

//            if (x < 0 || x >= this.Width ||
//                y < 0 || y >= this.Height ||
//                z < 0 || z >= this.Width)
//            {
//                success = false;
//                result = null;
//            }
//            else
//            {
//                success = true;
//                result = this.blocks[x, y, z];
//            }

//            return success;
//        }
//    }
//}
